import { ExtractJwt, Strategy } from 'passport-jwt';
import { PassportStrategy } from '@nestjs/passport';
import { BadRequestException, HttpException, HttpStatus, Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { UserService } from '@/modules/user/user.service';
import { RedisService } from '@/shared/redis.service';

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor(
    protected configService: ConfigService,
    private userService: UserService,
    private redisService: RedisService,
  ) {
    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      ignoreExpiration: false,
      secretOrKey: process.env.JWT_SECRET || configService.get('JWT_SECRET'),
      passReqToCallback: true,
    });
  }

  async validate(req: Request, payload: any) {
    const authHeader = req.headers['authorization'] ?? '';
    const reqToken = authHeader.split(' ')[1]; // Assuming the token is a Bearer token
    const userRedisToken = await this.redisService.get(`USER_ACCESS_TOKEN:${payload.userId}`);
    if (!userRedisToken) throw new HttpException('Token无效或已过期', HttpStatus.UNAUTHORIZED);
    if (reqToken !== userRedisToken) {
      await this.redisService.del(`USER_ACCESS_TOKEN:${payload.userId}`);
      throw new HttpException('Token无效或已过期', HttpStatus.UNAUTHORIZED);
    }
    const userID = payload.userId;
    const userInfo = JSON.parse(await this.redisService.get(`USER_INFO:${userID}`));
    // console.log('userInfo', userInfo);
    if (!userInfo) {
      await this.redisService.del(`USER_ACCESS_TOKEN:${userID}`);
      throw new HttpException('Token无效或已过期', HttpStatus.UNAUTHORIZED);
    }
    // 返回用户信息,将会注入到request中
    return {
      userId: userInfo.userId,
      phoneNumber: userInfo.phoneNumber,
      username: userInfo.username,
      email: userInfo.email,
      nickName: userInfo.nickName,
      birthdayDate: userInfo.birthdayDate,
      permissionIds: userInfo.permissionIds,
      roles: userInfo.roles,
      currentRole: userInfo.currentRole,
    };
  }
}
